package src.model.gameObject.eventBrokers;


import src.model.gameObject.GameObject;
import src.model.gameObject.eventInterfaces.MovePositionListener;
import src.model.gameObject.eventInterfaces.MoveGameObjectListener;
import src.model.gameWorld.Position;
import java.util.HashMap;
import java.util.Vector;

/**
 * This is the manager for move events. NOTE: This is not a Java awt event, it
 * it is notified through a method call, not an event. It maps positions to listeners, so that
 * @author Tristan
 *
 */
public class MoveEventBroker {

	private static MoveEventBroker staticReference;

	private HashMap<Position, Vector<MovePositionListener>> PositionToListener;
	private HashMap<MovePositionListener, Position> ListenerToPosition;
	private HashMap<GameObject, Vector<MoveGameObjectListener>> GameObjectToListener;
	private HashMap<MoveGameObjectListener, GameObject> ListenerToGameObject;

	/**
	 *
	 *
	 */
	public MoveEventBroker() {
		staticReference = this;
		PositionToListener = new HashMap<Position, Vector<MovePositionListener>>();
		ListenerToPosition = new HashMap<MovePositionListener, Position>();
		GameObjectToListener = new HashMap<GameObject, Vector<MoveGameObjectListener>>();
		ListenerToGameObject = new HashMap<MoveGameObjectListener, GameObject>();
	}

	/**
	 * This is called when an object implementing MovePositionListener wishes to be notified whenever something moves
	 * onto its position.
	 *
	 * @param p The position the MovePositionListener is listening for moves onto.
	 * @param m The MovePositionListener to be associated with the Position.
	 */
	public static void register(Position p, MovePositionListener m){
		Vector<MovePositionListener> listeners = staticReference.PositionToListener.get(p);
		if (listeners == null) listeners = new Vector<MovePositionListener>();
		listeners.add(m);
		staticReference.PositionToListener.put(p, listeners);

		staticReference.ListenerToPosition.put(m, p);
	}

	/**
	 *
	 * @param go
	 * @param m
	 */
	public static void register(GameObject go, MoveGameObjectListener m){
		Vector<MoveGameObjectListener> listeners = staticReference.GameObjectToListener.get(go);
		if (listeners == null) listeners = new Vector<MoveGameObjectListener>();
		listeners.add(m);
		staticReference.GameObjectToListener.put(go, listeners);

		staticReference.ListenerToGameObject.put(m, go);
	}

	public static void unregister(Position p, MovePositionListener m){
		staticReference.PositionToListener.remove(p);
		staticReference.ListenerToPosition.remove(m);
	}

	public static void unregister(GameObject go, MoveGameObjectListener m){
		staticReference.GameObjectToListener.remove(go);
		staticReference.ListenerToGameObject.remove(m);
	}

	/**
	 * To be called when a move happens. This allows the MoveEventBroker to notify everything that wishes to be
	 * notified
	 *
	 * @param go The GameObject that moved.
	 * @param p The Position that the GameObject moved onto.
	 */
	public static void recognizeMove(GameObject go, Position p){
		Vector<MovePositionListener> positionListeners = staticReference.PositionToListener.get(p);
		if (positionListeners != null){
			System.out.print("tim fix yo shit");
			for (MovePositionListener pl:positionListeners){
				pl.notifyPositionMovedOnto(go);
			}
		}

		Vector<MoveGameObjectListener> gameObjectListeners = staticReference.GameObjectToListener.get(go);
		if (gameObjectListeners != null) {
			for (MoveGameObjectListener gol:gameObjectListeners){
				gol.notifyGameObjectMoved(p);
			}
		}
	}

	/**
	 *
	 * @param m
	 * @param p
	 */
	public static void remapListener(MovePositionListener m, Position p){
		Position mover = staticReference.ListenerToPosition.get(m);
		Vector<MovePositionListener> listener = staticReference.PositionToListener.get(mover);
		listener = staticReference.PositionToListener.get(p);
		listener.add(m);
	}

	public static void remapListener(MoveGameObjectListener m, GameObject go){

		GameObject owner = staticReference.ListenerToGameObject.get(m);
		Vector<MoveGameObjectListener> listener = staticReference.GameObjectToListener.get(owner);
		listener = staticReference.GameObjectToListener.get(go);
		listener.add(m);
	}
}
